Почему я не могу получить воспроизводимые результаты в Керасе, даже если я установил случайные семена? - PullRequest
0 голосов
/ 02 июня 2018

Я тренирую архитектуру MobileNet на фиктивных данных с помощью Keras, на Mac OSX.Я установил nump.random и tensorflow.set_random_seed, но по некоторым причинам я не могу получить воспроизводимые результаты: каждый раз, когда я перезапускаю код, я получаю разные результаты.Зачем?Это не связано с графическим процессором, потому что я работаю на MacBook Pro 2017 с видеокартой Radeon, поэтому Tensorflow не использует его в своих интересах.Код запускается с

python Keras_test.py

, поэтому это не проблема состояния (я не использую Jupyter или IPython: среда должна сбрасываться при каждом запуске кода).

РЕДАКТИРОВАТЬ : я изменил свой код, переместив настройку всех семян до импорта Keras.Результаты по-прежнему не являются детерминированными, однако разница в результатах намного меньше, чем была раньше.Это очень странно.

Текущая модель очень мала (с точки зрения глубокой нейронной сети), не будучи тривиальной, ей не нужен графический процессор, и она обучается за несколько минут на современном ноутбуке.так что повторить мои эксперименты в пределах досягаемости.Я приглашаю вас сделать это: мне было бы очень интересно узнать об уровне вариации от системы к другой.

import numpy as np
# random seeds must be set before importing keras & tensorflow
my_seed = 512
np.random.seed(my_seed)
import random 
random.seed(my_seed)
import tensorflow as tf
tf.set_random_seed(my_seed)

# now we can import keras
import keras.utils
from keras.applications import MobileNet
from keras.callbacks import ModelCheckpoint
from keras.optimizers import Adam
import os

height = 224
width = 224
channels = 3
epochs = 10
num_classes = 10



# Generate dummy data
batch_size = 32  
n_train = 256
n_test = 64
x_train = np.random.random((n_train, height, width, channels))
y_train = keras.utils.to_categorical(np.random.randint(num_classes, size=(n_train, 1)), num_classes=num_classes)
x_test = np.random.random((n_test, height, width, channels))
y_test = keras.utils.to_categorical(np.random.randint(num_classes, size=(n_test, 1)), num_classes=num_classes)
# Get input shape
input_shape = x_train.shape[1:]

# Instantiate model 
model = MobileNet(weights=None,
                  input_shape=input_shape,
                  classes=num_classes)

model.compile(loss='categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])
# Viewing Model Configuration
model.summary()

# Model file name
filepath = 'model_epoch_{epoch:02d}_loss_{loss:0.2f}_val_{val_loss:.2f}.hdf5'

# Define save_best_only checkpointer
checkpointer = ModelCheckpoint(filepath=filepath,
                             monitor='val_acc',
                             verbose=1,
                             save_best_only=True)

# Let's fit!
model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          validation_data=(x_test, y_test),
          callbacks=[checkpointer])

Как всегда, вот мои версии Python, Keras & Tensorflow:

python -c 'import keras; import tensorflow; import sys; print(sys.version, 'keras.__version__', 'tensorflow.__version__')'
/anaconda2/lib/python2.7/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters
Using TensorFlow backend.
('2.7.15 |Anaconda, Inc.| (default, May  1 2018, 18:37:05) \n[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]', '2.1.6', '1.8.0')

Вот некоторые результаты, полученные при выполнении этого кода несколько раз: как вы можете видеть, код сохраняет лучшую модель (лучшую точность проверки) из 10 эпох с описательным именем файла, поэтому сравнение имен файлов при разных запусках позволяетсудить об изменчивости результатов.

model_epoch_01_loss_2.39_val_3.28.hdf5
model_epoch_01_loss_2.39_val_3.54.hdf5
model_epoch_01_loss_2.40_val_3.47.hdf5
model_epoch_01_loss_2.41_val_3.08.hdf5

Ответы [ 2 ]

0 голосов
/ 20 июля 2019

Ключевым моментом для получения воспроизводимого результата является отключение графического процессора.Смотрите мой ответ на другой вопрос (ссылка https://stackoverflow.com/a/57121117/9501391), который был принят.

0 голосов
/ 19 октября 2018

Вы можете найти ответ в Keras docs: https://keras.io/getting-started/faq/#how-can-i-obtain-reproducible-results-using-keras-during-development.

Короче говоря, чтобы быть абсолютно уверенным, что вы получите воспроизводимые результаты с вашим скриптом Python на ЦП одного компьютера / ноутбука тогда вам нужно будет сделать следующее:

  1. Установить PYTHONHASHSEED переменную среды с фиксированным значением
  2. Установить python встроенный псевдослучайный генератор с фиксированным значением
  3. Установить numpy псевдослучайный генератор с фиксированным значением
  4. Установить tensorflow псевдослучайный генератор с фиксированным значением
  5. Настроить новый глобальный tensorflow сеанс

По ссылке Keras вверху, я использую следующий исходный код:

# Seed value
# Apparently you may use different seed values at each stage
seed_value= 0

# 1. Set `PYTHONHASHSEED` environment variable at a fixed value
import os
os.environ['PYTHONHASHSEED']=str(seed_value)

# 2. Set `python` built-in pseudo-random generator at a fixed value
import random
random.seed(seed_value)

# 3. Set `numpy` pseudo-random generator at a fixed value
import numpy as np
np.random.seed(seed_value)

# 4. Set `tensorflow` pseudo-random generator at a fixed value
import tensorflow as tf
tf.set_random_seed(seed_value)

# 5. Configure a new global `tensorflow` session
from keras import backend as K
session_conf = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
sess = tf.Session(graph=tf.get_default_graph(), config=session_conf)
K.set_session(sess)

Нет необходимости говорить, что вам не нужно указыватьлюбые seed или random_state в функциях numpy, scikit-learn или tensorflow / keras, которые вы используете в своем скрипте python именно потому, что с исходным кодом выше мы устанавливаем глобально их псевдослучайные генераторы вфиксированное значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...